%function keyboard_tester_2014b
% i usually run this as a script
clear
close all
totalMemory=java.lang.Runtime.getRuntime.totalMemory;
freeMemory=java.lang.Runtime.getRuntime.freeMemory;
if freeMemory/totalMemory<.05
    fprintf('there is only %3.2f%% of free JAVA memory left\n -> exiting... please restart matlab\n',freeMemory/totalMemory*100);
    return
else
    fprintf('started with %3.2f%% of free JAVA memory left\n',freeMemory/totalMemory*100);
end

kk=load_win_keyboard;
%c=define_colors(uint8(256)); my definitions
c.D_GREY=uint8([77 77 77]);
c.BLUE=uint8([0 0 255]);
c.BACKGROUND=c.D_GREY;
ListenChar(0);% release keyboard from other users
uimenufcn(0,'WindowCommandWindow');
KbQueueCreate;

KbQueueStart;
if Eyelink('Initialize', 'PsychEyelinkDispatchCallback')
    InitializeDummy=questdlg_offscreen('Eyelink is not properly connected. Initialize in Dummy mode?', ...
        'Eyelink is not connected!', ...
        'Yes','Quit','Yes');
    if strcmp(InitializeDummy,'Yes')
        InitializeDummy=true;
        if Eyelink('InitializeDummy', 'PsychEyelinkDispatchCallback')
            fprintf('InitializeDummy failed too\n')
            return;
        end
    else
        fprintf('cancled by user\n')
        return;
    end
else
    InitializeDummy=false;
end
try
    oldLevel = Screen('Preference', 'VisualDebugLevel', 1); %level 1: error only
    oldEnableFlag = Screen('Preference', 'SuppressAllWarnings', 1);
    Screen('Preference', 'SkipSyncTests', 1);
    HideCursor
    [w, wRect]=Screen('OpenWindow', 2);
    %[w, wRect]=Screen('OpenWindow', screennum, 0,[],32,2);
    Screen(w,'BlendFunction',GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    % needed for proper anti-aliasing (smoothing) by Screen('DrawLines'), Screen('DrawDots') and for
    % drawing masked stimuli with the Screen('DrawTexture') command. See DotDemo,
    % LinesDemo, AlphaImageDemo, GazeContingentDemo for a few applications of
    % alpha-blending.
    pause(.01);
    Screen('fillrect',w,c.BACKGROUND);
    Screen('flip',w)
    screenpixW=wRect(3);
    screenpixH=wRect(4);
    c_x=round(double(screenpixW/2)); % the stupid text commands require a double for pixels placement
    c_y=round(double(screenpixH/2));
    Screen('TextStyle',w,1);% 0=plain, 1=bold, 2=italics, 3=1&2,  4=underlined, 5=4&1,6=4&2, 7=4&3. rem(?,8)
    Screen('TextFont',w,'Tahoma');
    Screen('TextSize',w,40);
    centertextY=c_y-40*.8;
    
    %
    el = EyelinkInitDefaults(w);
    %el.msgfont='Tahoma';
    el.msgfontsize=15;%12
    %el.imgtitlefont='Tahoma';
    el.imgtitlefontsize=12;
    PsychEyelinkDispatchCallback(el); % need to update el on the host
    
    KbQueueCreate;
    
    KbQueueStart;
    warning('off', 'PTB3:KbQueueBusy')
    ListenChar(2);% BLOCK keyboard from MATLAB
    warning('on', 'PTB3:KbQueueBusy')
    h2=update_info;
    
    KbQueueFlush();

    %keypress=0;
    keycode=0;
    lastkeycode=0;
    my_range=single(.1:.1:200);
    fred=single(zeros(length(my_range),1));
    Eyelink('StartRecording'); % messages must be AFTER StartRecording and require SPRINTF to convert floats to strings
    Eyelink('Command','clear_screen 0');
    Eyelink('Command','draw_text %d %d %d %s ',round(c_x),round(c_y),8,'GO!');
    DrawFormattedText(w,'GO!','center',centertextY,c.BLUE);
    update_info(h2,{'GO!'});
    Screen('flip',w);
    abs_start_time=round(GetSecs*1000);
    EL1k_start_time = round(Eyelink('TrackerTime')*1000);

    while keycode~=27
        us_start_time=round(GetSecs*10000);
        [keypress, keycodes, keytimes]= Kb_bcoeMS(abs_start_time);
        if keypress
            if keycodes(1)~=lastkeycode
                lastkeycode=keycodes(1);
                keycode=keycodes(1);
                keytime=keytimes(1);
                ttext=sprintf('T:%d C:%d (%s)',keytime, keycode,kk{keycode});
                fprintf('%s\n',ttext)
                Eyelink('Command','clear_screen 0');
                Eyelink('Command','draw_text %d %d %d %s ',round(c_x),round(c_y),8,ttext);
                DrawFormattedText(w,ttext,'center',centertextY,c.BLUE);
                Screen('flip',w,0,[],2);
                update_info(h2,{ttext});
            end
        else
            [samples, eventsIN] = Eyelink('GetQueuedData');
            if ~isempty(eventsIN),
                sidewinder=eventsIN(:,eventsIN(2,:)==25);
                if any(sidewinder)
                    keyCodes=sidewinder(3,:);
                    keyTimes=sidewinder(1,:)-EL1k_start_time;
                    %[keyCode, loc,loc2]=intersect([SW.cell{:}],keyCodes);
                    keyCode=keyCodes(1);
                    if any(keyCode) && length(keyCode)==1 % only except one key press per 2ms
                        effector='sidewinder';
                        %keyTime=keyTimes(loc2);
                        keyTime=keyTimes(1);
                        ttext=sprintf('keyCode=%2d:  Time=%10d (%s)',keyCode,keyTime,effector);% requires SPRINTF
                        Eyelink('Command','clear_screen 0');
                        Eyelink('Command','draw_text %d %d %d %s ',round(c_x),round(c_y),8,ttext);
                        DrawFormattedText(w,ttext,'center',centertextY,c.BLUE);
                        Screen('flip',w);
                        update_info(h2,{ttext});
                    else
                        beep;
                    end
                end %if any(sidewinder)
            end% ~isempty(eventsIN)
        end % ~keypress
        us_stamp=round(GetSecs*10000)-us_start_time+1;
        fred(us_stamp)=fred(us_stamp)+1;% histogram   
        if my_range(us_stamp)>50
            if sum(fred(my_range>50))>1
            crash
            end
        end
    end
catch badness
    badness.message
    badness.stack.name
    badness.stack.line
end
Screen('closeall');
update_info(-1);
ShowCursor;
figure(2);clf;stairs(my_range,fred,'r')
ylim([0 10])
figure(2);clf;stairs(my_range,cumsum(fred)/sum(fred)*100,'r')

ListenChar(0);% release keyboard 
KbQueueStop;
KbQueueRelease;
Eyelink('StopRecording'); % messages must be AFTER StartRecording and require SPRINTF to convert floats to strings
Eyelink('Shutdown');
fprintf(' !!!FIN!!!\n\n')